package com.ejlchina.tool.fragment.offline

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.adolf.androiddemo.R
import com.adolf.androiddemo.databinding.DialogIndexFixSelectIndexBinding
import com.adolf.androiddemo.databinding.FragmentPushRodParametersOfflineBinding
import com.ejlchina.tool.adapter.DeviceAdapterRadioOffline
import com.ejlchina.tool.adapter.IndexFixDialogAdapter
import com.ejlchina.tool.base.BaseBindingFragment2
import com.ejlchina.tool.bean.BleDeviceBean
import com.ejlchina.tool.bean.PushRodBean
import com.ejlchina.tool.constant.OFFLINE_DEVICE_LEFT
import com.ejlchina.tool.constant.OFFLINE_DEVICE_RIGHT
import com.ejlchina.tool.enums.AntiPinchModeEnum
import com.ejlchina.tool.enums.OnOffEnum
import com.ejlchina.tool.enums.RotateDirectionEnum
import com.ejlchina.tool.singleton.GlobalConnectObject
import com.ejlchina.tool.util.COMMAND_PUSH_ROD_GET_DOWNWARD
import com.ejlchina.tool.util.COMMAND_PUSH_ROD_GET_UPWARD
import com.ejlchina.tool.util.COMMAND_PUSH_ROD_SET_UPWARD
import com.ejlchina.tool.util.COMMAND_SET_ELECTRICAL_MACHINERY_DOWNWARD
import com.ejlchina.tool.util.bytearray.intTo32HexStringLE
import com.ejlchina.tool.util.bytearray.intToByteHexString
import com.ejlchina.tool.util.bytearray.readByteArrayLE
import com.ejlchina.tool.util.bytearray.toHexString
import com.ejlchina.tool.util.getIntFromByteArray
import com.ejlchina.tool.util.showToast
import com.ejlchina.tool.view.GridItemDecoration
import com.google.android.material.bottomsheet.BottomSheetDialog
import com.huyuhui.fastble.data.BleDevice
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

class PushRodParametersOfflineFragment: BaseBindingFragment2<FragmentPushRodParametersOfflineBinding>() {

    private val pushRodBeanLeft = PushRodBean()
    private val pushRodBeanRight = PushRodBean()
    private val machineAntiPinchArray = arrayListOf(AntiPinchModeEnum.NO_ANTI_PINCH,AntiPinchModeEnum.OPEN_ANTI_PINCH,AntiPinchModeEnum.CLOSE_ANTO_PINCH)
    private val closeDoorSection = arrayListOf(1,2,3)
    override fun getViewBinding(inflater: LayoutInflater, container: ViewGroup): FragmentPushRodParametersOfflineBinding {
        return FragmentPushRodParametersOfflineBinding.inflate(inflater,container,true)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initViews()
        initData()
    }

    private fun initViews(){
        setHeadTitle("推杆参数")
        setRightIconVisibility(View.GONE)
        initListeners()
        binding.includeAntiPinchLeft.layoutMachineAntiPinch.visibility = View.GONE
        binding.includeAntiPinchRight.layoutMachineAntiPinch.visibility = View.GONE
    }

    private fun initData(){
        initDevices()
    }

    private fun initListeners(){
        binding.includeAntiPinchLeft.radioGroup.setOnCheckedChangeListener{ _, checkedId ->
            when (checkedId) {
                R.id.rb_cw -> pushRodBeanLeft.rotateDirection = RotateDirectionEnum.CW
                R.id.rb_ccw -> pushRodBeanLeft.rotateDirection = RotateDirectionEnum.CCW
            }
        }
        binding.includeAntiPinchRight.radioGroup.setOnCheckedChangeListener { _, checkedId ->
            when (checkedId) {
                R.id.rb_cw -> pushRodBeanRight.rotateDirection = RotateDirectionEnum.CW
                R.id.rb_ccw -> pushRodBeanRight.rotateDirection = RotateDirectionEnum.CCW
            }
        }

        binding.includeAntiPinchLeft.antiPinchRadioGroup.setOnCheckedChangeListener { _, checkedId ->
            when(checkedId){
                R.id.rb_anti_pinch_on -> pushRodBeanLeft.machineAntiPinch = AntiPinchModeEnum.CLOSE_ANTO_PINCH
                R.id.rb_anti_pinch_off -> pushRodBeanLeft.machineAntiPinch = AntiPinchModeEnum.NO_ANTI_PINCH
            }
        }
        binding.includeAntiPinchRight.antiPinchRadioGroup.setOnCheckedChangeListener { _, checkedId ->
            when(checkedId){
                R.id.rb_anti_pinch_on -> pushRodBeanRight.machineAntiPinch = AntiPinchModeEnum.CLOSE_ANTO_PINCH
                R.id.rb_anti_pinch_off -> pushRodBeanRight.machineAntiPinch = AntiPinchModeEnum.NO_ANTI_PINCH
            }
        }

        binding.includeDoorSectionLeft.tvCloseDoorSectionCount.setOnClickListener {
            showCloseCountBottom{ selectCount ->
                binding.includeDoorSectionLeft.tvCloseDoorSectionCount.text = selectCount.toString()
                binding.includeDoorSectionLeft.layoutIntervalTime.visibility = if (selectCount == 1) View.GONE else View.VISIBLE
                if (selectCount == 1){
                    pushRodBeanLeft.closeSectionDelay = 0
                    binding.includeDoorSectionLeft.etInterval.setText(pushRodBeanLeft.closeSectionDelay.toString())
                }
                pushRodBeanLeft.closeSectionCount = selectCount
            }
        }

        binding.includeDoorSectionRight.tvCloseDoorSectionCount.setOnClickListener {
            showCloseCountBottom{ selectCount ->
                binding.includeDoorSectionRight.tvCloseDoorSectionCount.text = selectCount.toString()
                binding.includeDoorSectionRight.layoutIntervalTime.visibility = if (selectCount == 1) View.GONE else View.VISIBLE
                if (selectCount == 1){
                    pushRodBeanRight.closeSectionDelay = 0
                    binding.includeDoorSectionRight.etInterval.setText(pushRodBeanRight.closeSectionDelay.toString())
                }
                pushRodBeanRight.closeSectionCount = selectCount
            }
        }

        binding.btnConfirm.setOnClickListener {
            setPushRodData(deviceAdapterOffline.getSelectDevice(),pushRodBeanLeft, OFFLINE_DEVICE_LEFT)
        }

        binding.includeDoorSectionLeft.etEveryTravelTime.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanLeft.closeSectionDuration = it.toString().toInt()
                }
            }
        }

        binding.includeDoorSectionRight.etEveryTravelTime.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanRight.closeSectionDuration = it.toString().toInt()
                }
            }
        }

        binding.includeDoorSectionLeft.etCloseDelay.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanLeft.autoCloseDelay = it.toString().toInt()
                }
            }
        }

        binding.includeDoorSectionRight.etCloseDelay.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanRight.autoCloseDelay = it.toString().toInt()
                }
            }
        }

        binding.includeDoorSectionLeft.etInterval.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanLeft.closeSectionDelay = it.toString().toInt()
                }
            }
        }

        binding.includeDoorSectionRight.etInterval.doAfterTextChanged {
            it?.let {
                if (it.isNotEmpty()){
                    pushRodBeanRight.closeSectionDelay = it.toString().toInt()
                }
            }
        }
    }

    private fun showCloseCountBottom(clickCallback: (Int) -> Unit){
        val indexFixDialogAdapter = IndexFixDialogAdapter(closeDoorSection)
        val layoutBinding = DialogIndexFixSelectIndexBinding.inflate(LayoutInflater.from(binding.root.context),null,false)
        val bottomSheetDialog = BottomSheetDialog(binding.root.context, R.style.bottom_sheet_dialog)
        layoutBinding.recyclerView.apply {
            adapter = indexFixDialogAdapter
            layoutManager = LinearLayoutManager(binding.root.context)
        }
        layoutBinding.tvCancel.setOnClickListener {
            bottomSheetDialog.dismiss()
        }
        layoutBinding.tvConfirm.setOnClickListener {
            clickCallback(indexFixDialogAdapter.getSelectIndex())
            bottomSheetDialog.dismiss()
        }
        bottomSheetDialog.setContentView(layoutBinding.root)
        bottomSheetDialog.show()
    }

    override fun whenReceiveCommand(bleDevice: BleDeviceBean,command: String, commandByteArray: ByteArray) {
        super.whenReceiveCommand(bleDevice,command, commandByteArray)
        when (command){
            COMMAND_PUSH_ROD_GET_UPWARD -> {
                viewLifecycleOwner.lifecycleScope.launch {
                    val pushRodBean = if (commandByteArray[0].toInt() == OFFLINE_DEVICE_LEFT) pushRodBeanLeft else pushRodBeanRight
                    setPushBeanData(pushRodBean,commandByteArray)
                    setUIData(pushRodBean,commandByteArray[0].toInt())
                    if (commandByteArray[0].toInt() == OFFLINE_DEVICE_LEFT){
                        delay(500)
                        getPushRodData(bleDevice, OFFLINE_DEVICE_RIGHT)
                    }else {
                        dismissLoading()
                    }
                }
            }

            COMMAND_PUSH_ROD_SET_UPWARD -> {
                viewLifecycleOwner.lifecycleScope.launch {
                    val result = commandByteArray[commandByteArray.size - 1].toInt()
                    if (commandByteArray[0].toInt() == OFFLINE_DEVICE_LEFT){
                        delay(500)
                        setPushRodData(deviceAdapterOffline.getSelectDevice(),pushRodBeanRight, OFFLINE_DEVICE_RIGHT)
                    } else {
                        dismissLoading()
                        setResultToast(result)
                    }
                }

            }
        }

    }


    private fun setPushBeanData(pushRodBean: PushRodBean, byteArray: ByteArray){
        when(byteArray[0].toInt()){
            0 -> pushRodBean.machineAntiPinch = AntiPinchModeEnum.NO_ANTI_PINCH
            else -> pushRodBean.machineAntiPinch = AntiPinchModeEnum.CLOSE_ANTO_PINCH

        }
        pushRodBean.electricAntiPinch = OnOffEnum.getFromIndex(byteArray[1].toInt())
        when(byteArray[2].toInt()){
            0 -> pushRodBean.rotateDirection = RotateDirectionEnum.CW
            1 -> pushRodBean.rotateDirection = RotateDirectionEnum.CCW
        }
        pushRodBean.autoCloseDelay = getIntFromByteArray(byteArray.readByteArrayLE(3,4)) / 1000
        pushRodBean.closeSectionCount = byteArray[7].toInt()
        pushRodBean.closeSectionDuration = getIntFromByteArray(byteArray.readByteArrayLE(8,4)) / 1000
        pushRodBean.closeSectionDelay = getIntFromByteArray(byteArray.readByteArrayLE(20,4)) / 1000
    }
    override fun whenDeviceDisConnect(disConnectDevice: BleDevice) {
        super.whenDeviceDisConnect(disConnectDevice)

    }

    private fun setUIData(pushRodBean: PushRodBean,pushGate: Int){
        checkAntiPinchRadioButton(pushRodBean.machineAntiPinch.index,pushGate)
        checkRadioButton(pushRodBean.rotateDirection.index,pushGate)
        val includeView = if (pushGate == OFFLINE_DEVICE_LEFT) binding.includeDoorSectionLeft else binding.includeDoorSectionRight
        includeView.etCloseDelay.setText(pushRodBean.autoCloseDelay.toString())
        includeView.tvCloseDoorSectionCount.text = pushRodBean.closeSectionCount.toString()
        val isCloseDoorSectionSettingVisible = pushRodBean.closeSectionCount > 1
        includeView.layoutIntervalTime.visibility = if (isCloseDoorSectionSettingVisible) View.VISIBLE else View.GONE
        includeView.etEveryTravelTime.setText(pushRodBean.closeSectionDuration.toString())
        includeView.etInterval.setText(pushRodBean.closeSectionDelay.toString())
    }

    private fun checkRadioButton(index: Int,pushGate: Int){
        val includeView = if (pushGate == OFFLINE_DEVICE_LEFT) binding.includeAntiPinchLeft else binding.includeAntiPinchRight
        val id = when(index){
            0 -> includeView.rbCw.id
            else -> includeView.rbCcw.id
        }
        includeView.radioGroup.check(id)
    }

    private fun checkAntiPinchRadioButton(index: Int,pushGate: Int){
        val includeView = if (pushGate == OFFLINE_DEVICE_LEFT) binding.includeAntiPinchLeft else binding.includeAntiPinchRight
        val checkId = when(index){
            0 -> includeView.rbAntiPinchOff.id
            else -> includeView.rbAntiPinchOn.id
        }
        includeView.antiPinchRadioGroup.check(checkId)
    }

    private fun getPushRodData(bleDevice: BleDeviceBean, pushGate: Int){
        getCommandData(bleDevice,COMMAND_PUSH_ROD_GET_DOWNWARD, commandVariable = intToByteHexString(pushGate))
    }
    private fun initDevices(){
        deviceAdapterOffline = DeviceAdapterRadioOffline(GlobalConnectObject.getCurrentConnectDeviceList()){
            getPushRodData(it, OFFLINE_DEVICE_LEFT)
        }
        binding.rvDevices.apply {
            adapter = deviceAdapterOffline
            layoutManager = GridLayoutManager(requireContext(),3)
            if (itemDecorationCount == 0){
                addItemDecoration(GridItemDecoration(3,11,11))
            }
        }
    }



    private fun setPushRodData(bleDevice: BleDeviceBean,pushRodBean: PushRodBean,pushGate: Int){
        if (!checkInputData()) return
        val commandStringBuffer = StringBuffer()
        commandStringBuffer.append(intToByteHexString(pushGate))
        commandStringBuffer.append(intToByteHexString(0)) //预留字段
        commandStringBuffer.append(pushRodBean.rotateDirection.index.toHexString()) //开门动作时推杆转动方向
        commandStringBuffer.append(intTo32HexStringLE(pushRodBean.autoCloseDelay * 1000)) //自动关门延时时间
        commandStringBuffer.append(intToByteHexString(pushRodBean.closeSectionCount)) //几段式关门，范围 1-3
        setCloseSectionDuration(commandStringBuffer,pushRodBean)
        setCloseSectionDelay(commandStringBuffer,pushRodBean)
        setCommandData(bleDevice,COMMAND_SET_ELECTRICAL_MACHINERY_DOWNWARD,commandStringBuffer.toString())
    }

    private fun checkInputData(): Boolean {
        val closeDelayTimeLeft = binding.includeDoorSectionLeft.etCloseDelay.text.toString()
        val closeDelayTimeRight = binding.includeDoorSectionRight.etCloseDelay.text.toString()
        val everyTravelTimeLeft = binding.includeDoorSectionLeft.etEveryTravelTime.text.toString()
        val everyTravelTimeRight = binding.includeDoorSectionRight.etEveryTravelTime.text.toString()
        val intervalTimeLeft = binding.includeDoorSectionLeft.etInterval.text.toString()
        val intervalTimeRight = binding.includeDoorSectionRight.etInterval.text.toString()

        if (closeDelayTimeLeft.isEmpty()) {
            showToast("请输入投口1关门延迟时间")
            return false
        }

        if (closeDelayTimeRight.isEmpty()) {
            showToast("请输入投口2关门延迟时间")
            return false
        }

        if (closeDelayTimeLeft.toInt() < 5 || closeDelayTimeLeft.toInt() > 300) {
            showToast("投口1关门延迟时间应该在5到300秒之间")
            return false
        }

        if (closeDelayTimeRight.toInt() < 5 || closeDelayTimeRight.toInt() > 300) {
            showToast("投口2关门延迟时间应该在5到300秒之间")
            return false
        }


        if (everyTravelTimeLeft.isEmpty()) {
            showToast("请输入投口1每段行程时间")
            return false
        }

        if (everyTravelTimeRight.isEmpty()) {
            showToast("请输入投口2每段行程时间")
            return false
        }

        if (everyTravelTimeLeft.toInt() <= 0 || everyTravelTimeLeft.toInt() > 99) {
            showToast("投口1每段行程时间应该在1到99秒之间")
            return false
        }

        if (everyTravelTimeRight.toInt() <= 0 || everyTravelTimeRight.toInt() > 99) {
            showToast("投口2每段行程时间应该在1到99秒之间")
            return false
        }

        if (intervalTimeLeft.isEmpty()) {
            showToast("请输入投口1间隔等待时间")
            return false
        }

        if (intervalTimeRight.isEmpty()) {
            showToast("请输入投口2间隔等待时间")
            return false
        }

        if (intervalTimeLeft.toInt() > 99) {
            showToast("投口1间隔等待时间应该在0到99秒之间")
            return false
        }

        if (intervalTimeRight.toInt() > 99) {
            showToast("投口2间隔等待时间应该在0到99秒之间")
            return false
        }

        return true
    }

    private fun coverString(stringBuffer: StringBuffer){
        stringBuffer.append(intTo32HexStringLE(0))
    }

    private fun setCloseSectionDuration(stringBuffer: StringBuffer, pushRodBean: PushRodBean){
        val closeSectionCount = pushRodBean.closeSectionCount
        for (item in 1 ..closeSectionCount){
            stringBuffer.append(intTo32HexStringLE(pushRodBean.closeSectionDuration * 1000))
        }
        for (item in closeSectionCount until 3){
            coverString(stringBuffer)
        }
    }

    private fun setCloseSectionDelay(stringBuffer: StringBuffer,pushRodBean: PushRodBean){
        for (item in 1 ..2){
            stringBuffer.append(intTo32HexStringLE(pushRodBean.closeSectionDelay * 1000))
        }
    }
}